/*****************************************************************************
 *  ENTROPY - emerging network to reduce orwellian potency yield
 *
 *  Copyright (C) 2002 Juergen Buchmueller <pullmoll@stop1984.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software Foundation,
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 *	$Id: gif.h,v 1.2 2005/07/12 23:19:26 pullmoll Exp $
 *****************************************************************************/
#ifndef	_gif_h_
#define	_gif_h_

#include "osd.h"
#include "memalloc.h"
#include "logger.h"

#ifndef	INLINE
#define	INLINE	__inline
#endif

/* define constants and defaults */
/* default amount of inter-frame time */
#define DEFAULT_TIME 10
/* if set to 1, Netscape 'loop' code will be added by default */
#define DEFAULT_LOOP 0
/* if set to 1, use the colormaps from all images, not just the first */
#define DEFAULT_USE_COLORMAP 0

/* used in calculating the transparent color */
#define TRANS_NONE 1
#define TRANS_RGB 2
#define TRANS_MAP 3

/* set default disposal method here to any of the DISP_XXXX values */
#define DISP_NONE 0
#define DISP_NOT  1
#define DISP_BACK 2
#define DISP_PREV 3
#define DEFAULT_DISPOSAL DISP_NONE

#define BIGSTRING 256
/* maxval of lzw coding size */
#define LZW_MAXVAL  4096
#define NODE_TERMIN 'T'
#define NODE_LOOKUP 'L'
#define NODE_SEARCH 'S'
#define NODE_ARRAY_MAX 20
/* defines the amount of memory set aside in the encoding for the
 * LOOKUP type nodes; for a 256 color GIF, the number of LOOKUP
 * nodes will be <= noOfArrays, for a 128 color GIF the number of
 * LOOKUP nodes will be <= 2 * noOfArrays, etc.
 */

/* gif_blit modes supported */
#define	GIF_BLITCOPY	0		/* copy pixels (set both, fg and bg) */
#define	GIF_BLITSET		1		/* set pixels (set only fg pixels) */

/* definition of various structures */
typedef struct gif_transparency_s {
	int type;
	uint8_t valid;			/* non-zero if the entry is valid */
	uint8_t map;			/* color map index of the transparent color */
	uint8_t red;			/* red transparency value */
	uint8_t green;			/* green transparency value */
	uint8_t blue;			/* blue transparency value */
}	gif_transparency_t;

typedef struct gif_tree_s {
	char type;				/* terminating, lookup, or search */
	uint8_t ix;			/* the color map index */
	short code;				/* the code to be output */
	struct gif_tree_s **node;
	struct gif_tree_s *next;
	struct gif_tree_s *alt;
}	gif_tree_t;

typedef struct gif_screen_hdr_s {
	int width;
	int height;
	uint8_t colormap;		/* 80: have a global colormap */
	uint8_t cres;			/* 70: color resolution */
	uint8_t sorted;		/* 08: palette is sorted */
	uint8_t bpp;			/* 07: bits per pixel */
	uint8_t bc;			/* background color index */
	uint8_t aspect;		/* aspect ratio */
}	gif_screen_hdr_t;

typedef union gif_color_u {
	struct cmap {
		uint8_t red;
		uint8_t green;
		uint8_t blue;
		uint8_t dummy;
	} cmap;
	uint32_t pixel;
}	gif_color_t;

typedef struct gif_image_hdr_s {
	int left;
	int top;
	int width;
	int height;
	uint8_t colormap;		/* 80: have a local colormap */
	uint8_t interlace;		/* 40: interlace mode */
	uint8_t sorted;		/* 20: sorted palette */
	uint8_t bpp;			/* 07: bits per pixel - 1 */
	uint8_t reserved;
}	gif_image_hdr_t;

typedef struct gif_global_s {
	gif_screen_hdr_t scr;
	gif_color_t gmap[256];
	gif_color_t cmap[256];
	gif_image_hdr_t img;
	uint8_t *picture;
}	gif_global_t;

typedef struct gif_encoder_s {
	int chainlen;
	int maxchainlen;
	int node_count;
	int node_lookups;
	int nbits;
	uint32_t need;
	uint32_t mask;
	gif_tree_t *empty[256];
	gif_tree_t root;
	gif_tree_t *top_node;
	gif_tree_t *base_node;
	gif_tree_t **node_array;
	gif_tree_t **last_array;
	char buff[1000];
}	gif_encoder_t;

typedef struct gif_decoder_s {
	uint32_t code_old;
	uint32_t code_size;
	uint32_t code_root;
	uint32_t expected;
	uint32_t need;
	uint32_t mask;
	int offs;
	int size;
	int pass;
	uint32_t first[LZW_MAXVAL];
	uint8_t code[LZW_MAXVAL];
	uint8_t last[LZW_MAXVAL];
	uint8_t *top_code;
}	gif_decoder_t;

typedef struct gif_s {
	void *user;
	int (*input)(void *user, void *buff, size_t size);
	int (*output)(void *user, const void *buff, size_t size);
	int frame_count;

	gif_encoder_t enc;
	gif_decoder_t dec;

	gif_transparency_t trans;
	int left;
	int top;
	int loop;
	unsigned int time;
	unsigned short disposal;
	gif_global_t old;

	gif_screen_hdr_t scr;
	gif_color_t gmap[256];
	gif_color_t cmap[256];
	gif_image_hdr_t img;
	uint8_t *picture;

}	gif_t;

#define	GIF_RGB_CONST(r,g,b)	{{r,g,b,0}}
#define	GIF_RGB_SET(pal,r,g,b) { \
	((gif_color_t *)(pal))->cmap.red = r; \
	((gif_color_t *)(pal))->cmap.green = g; \
	((gif_color_t *)(pal))->cmap.blue = b; \
}

#ifdef	__cplusplus
extern "C" {
#endif

char *gif_add_code(gif_t *gif, int code, int n, char *buf);
void gif_clear_tree(gif_t *gif, int cur_code, gif_tree_t *root);
void gif_clear_table(gif_t *gif);
void gif_decode(gif_t *gif);
void gif_encode(gif_t *gif, uint8_t *, int, int);
int gif_comment(gif_t *gif, const char *src);
int gif_loop(gif_t *gif, int loop);
int gif_append_file(gif_t *gif, const char *filename, int firstimage);
gif_t *gif_read_file(const char *filename);
gif_t *gif_create(int w, int h, int bpp, gif_color_t *palette,
	void *user, int (*output)(void *user, const void *buff, size_t size));
int gif_finish(gif_t *gif, int lastimage);
int gif_move(gif_t *gif, int xd, int yd, int xs, int ys, int w, int h);
int gif_blit(gif_t *gif, int xd, int yd, int w, int h,
	uint32_t *ppix, int rowsize, int fg, int bg, int mode);
int gif_set_pal(gif_t *gif, int color, gif_color_t *rgb);
int gif_put_pixel(gif_t *gif, int x, int y, int color);
int gif_put_hline(gif_t *gif, int x, int y, int w, uint8_t pattern, int color);
int gif_put_vline(gif_t *gif, int x, int y, int h, uint8_t pattern, int color);
int gif_rectangle(gif_t *gif, int x0, int y0, int x1, int y1, int color);
int gif_3d_rectangle(gif_t *gif, int x0, int y0, int x1, int y1,
	int topleft_color, int bottomright_color, int thickness);
int gif_filled_rectangle(gif_t *gif, int x0, int y0, int x1, int y1, int color);
int gif_printch(gif_t *gif, int x, int y, int color, int ch);
int gif_printf(gif_t *gif, int x, int y, int color, const char *fmt, ...);
int gif_read_screen_header(gif_t *gif, gif_t *gif_out, int firstimage);
uint8_t *gif_send_data(gif_t *gif, uint8_t *, int, uint8_t *);
int gif_read_image_header(gif_t *gif);
int gif_write_gcl(gif_t *gif);
int gif_write_image_header(gif_t *gif);

int gif(void);

#ifdef	__cplusplus
}
#endif

#endif	/* !defined(_gif_h_) */
